package utils

import (
	"context"
	"fmt"
	"github.com/go-redis/redis/v8"
	"sync"
	"time"
)

var (
	ctx  = context.Background()
	rdb  *redis.Client
	once sync.Once // 用于确保初始化只执行一次
)

// GetRedisClient 获取或初始化Redis客户端实例
func GetRedisClient() *redis.Client {
	once.Do(func() {
		// 连接到Redis
		rdb = redis.NewClient(&redis.Options{
			Addr:     "localhost:6379", // Redis服务器地址
			Password: "",               // 密码，没有则留空
			DB:       0,                // 使用默认数据库
		})
		// 测试连接
		pong, err := rdb.Ping(ctx).Result()
		if err != nil {
			fmt.Printf("Failed to connect to Redis: %v\n", err)
			return
		}
		fmt.Println("Connected to Redis:", pong)
	})
	return rdb
}

// String operations
func SetString(key string, value string, duration int) {
	rdb := GetRedisClient()
	if duration > 0 {
		// 将秒数转换为 time.Duration
		dur := time.Duration(duration) * time.Second
		rdb.Set(ctx, key, value, dur)
	} else {
		// 永久存储，不设置过期时间
		rdb.Set(ctx, key, value, 0)
	}
}

func GetString(key string) (string, error) {
	rdb := GetRedisClient()
	return rdb.Get(ctx, key).Result()
}

// List operations
func LPush(key string, values ...string) {
	rdb := GetRedisClient()
	rdb.LPush(ctx, key, values)
}

func RPop(key string) (string, error) {
	rdb := GetRedisClient()
	return rdb.RPop(ctx, key).Result()
}

// Set operations
func SAdd(key string, members ...string) {
	rdb := GetRedisClient()
	rdb.SAdd(ctx, key, members)
}

// SIsMember 检查成员是否已经存在于集合中
func SIsMember(key string, member string) (bool, error) {
	rdb := GetRedisClient()
	return rdb.SIsMember(ctx, key, member).Result()
}

func SMembers(key string) ([]string, error) {
	rdb := GetRedisClient()
	return rdb.SMembers(ctx, key).Result()
}

// Sorted Set operations
func ZAdd(key string, members ...*redis.Z) {
	rdb := GetRedisClient()
	rdb.ZAdd(ctx, key, members...)
}

func ZRange(key string, start, stop int64) ([]redis.Z, error) {
	rdb := GetRedisClient()
	return rdb.ZRangeWithScores(ctx, key, start, stop).Result()
}

// Hash operations
func HSet(key string, fields map[string]string) {
	rdb := GetRedisClient()
	rdb.HSet(ctx, key, fields)
}

func HGetAll(key string) (map[string]string, error) {
	rdb := GetRedisClient()
	return rdb.HGetAll(ctx, key).Result()
}
